package com.yic.module.mes.controller.admin.mo;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yic.framework.common.util.collection.CollectionUtils;
import com.yic.module.base.api.center.CenterApi;
import com.yic.module.base.api.center.dto.CenterRespDTO;
import com.yic.module.base.api.factory.FactoryApi;
import com.yic.module.base.api.factory.dto.FactoryRespDTO;
import com.yic.module.base.api.item.ItemApi;
import com.yic.module.base.api.item.dto.ItemRespDTO;
import com.yic.module.base.api.workshop.WorkshopApi;
import com.yic.module.base.api.workshop.dto.WorkshopRespDTO;
import com.yic.module.mes.api.moroute.MoRouteApi;
import com.yic.module.mes.api.moroute.dto.MoRouteRespDTO;
import com.yic.module.mes.controller.admin.moroute.vo.MoRouteRespVO;
import com.yic.module.mes.controller.admin.reportworkhours.vo.ReportWorkHoursFormsRespVO;
import com.yic.module.mes.dal.dataobject.moroute.MoRouteDO;
import com.yic.module.mes.dal.dataobject.plan.PlanDO;
import com.yic.module.mes.dal.dataobject.process.ProcessDO;
import com.yic.module.mes.service.moroute.MoRouteService;
import com.yic.module.mes.service.plan.PlanService;
import com.yic.module.mes.service.process.ProcessService;
import com.yic.module.mes.service.report.ReportService;
import com.yic.module.system.api.dept.DeptApi;
import com.yic.module.system.api.dept.dto.DeptRespDTO;
import com.yic.module.system.api.user.dto.AdminUserRespDTO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;

import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.math.BigDecimal;
import java.util.*;
import java.io.IOException;

import com.yic.framework.common.pojo.PageResult;
import com.yic.framework.common.pojo.CommonResult;
import static com.yic.framework.common.pojo.CommonResult.success;

import com.yic.framework.excel.core.util.ExcelUtils;

import com.yic.framework.operatelog.core.annotations.OperateLog;
import static com.yic.framework.operatelog.core.enums.OperateTypeEnum.*;

import com.yic.module.mes.controller.admin.mo.vo.*;
import com.yic.module.mes.dal.dataobject.mo.MoDO;
import com.yic.module.mes.convert.mo.MoConvert;
import com.yic.module.mes.service.mo.MoService;

@Tag(name = "管理后台 - 生产排产")
@RestController
@RequestMapping("/mes/mo")
@Validated
public class MoController {

    @Resource
    private MoService moService;
    @Resource
    private FactoryApi factoryApi;
    @Resource
    private DeptApi deptApi;
    @Resource
    private WorkshopApi workshopApi;
    @Resource
    private ItemApi itemApi;
    @Resource
    private PlanService planService;
    @Resource
    private MoRouteApi moRouteApi;
    @Resource
    private ReportService reportService;
    @Resource
    private ProcessService processService;

    @PostMapping("/create")
    @Operation(summary = "创建生产排产")
    @PreAuthorize("@ss.hasPermission('mes:mo:create')")
    public CommonResult<Boolean> createMo(@Valid @RequestBody MoBatchCreateReqVO createBatchReqVO) {
        moService.createMo(createBatchReqVO);
        return success(Boolean.TRUE);
    }

    @PutMapping("/update")
    @Operation(summary = "更新生产排产")
    @PreAuthorize("@ss.hasPermission('mes:mo:update')")
    public CommonResult<Boolean> updateMo(@Valid @RequestBody MoUpdateReqVO updateReqVO) {
        moService.updateMo(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除生产排产")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('mes:mo:delete')")
    public CommonResult<Boolean> deleteMo(@RequestParam("id") Long id) {
        moService.deleteMo(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得生产排产")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('mes:mo:query')")
    public CommonResult<MoRespVO> getMo(@RequestParam("id") Long id) {
        MoDO mo = moService.getMo(id);
        return success(MoConvert.INSTANCE.convert(mo));
    }

    @GetMapping("/info")
    @Operation(summary = "获得生产排产")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('mes:mo:query')")
    public CommonResult<MoRespVO> getMoInfo(@RequestParam("id") Long id) {
        MoDO mo = moService.getMo(id);
        MoRespVO resp = MoConvert.INSTANCE.convert(mo);
        if (ObjectUtil.isNotEmpty(resp)) {
            //封装工厂信息
            FactoryRespDTO factory = factoryApi.getFactory(resp.getFactoryId());
            if (ObjectUtil.isNotEmpty(factory)) {
                resp.setFactoryName(factory.getName());
            }
            // 封装生产车间
            WorkshopRespDTO workshop = workshopApi.getWorkshop(resp.getWorkshopId());
            if (ObjectUtil.isNotEmpty(workshop)) {
                resp.setWorkshopName(workshop.getName());
            }
            // 封装生产计划
            PlanDO plan = planService.getPlan(resp.getPlanId());
            if (ObjectUtil.isNotEmpty(plan)) {
                resp.setPlanCode(plan.getCode());
            }
            // 封装部门
            DeptRespDTO dept = deptApi.getDept(resp.getDeptId());
            if (ObjectUtil.isNotEmpty(dept)) {
                resp.setDeptName(dept.getName());
            }
            //封装产品信息
            ItemRespDTO item = itemApi.getItem(resp.getItemId());
            if (ObjectUtil.isNotEmpty(item)) {
                resp.setItemName(item.getName());
                resp.setItemCode(item.getCode());
                resp.setSpec(item.getSpec());
                resp.setDrawCode(item.getDrawCode());
            }
            // 封装工单工艺路线
            List<MoRouteRespDTO> routes = moRouteApi.getMoRouteList(resp.getId());

            // 查询已报工数据
            if (CollectionUtil.isNotEmpty(routes)) {
                Map<Long, BigDecimal> reportMap = reportService.getReportGroupByMoId(resp.getId());
                routes.forEach(moRouteRespDTO -> {
                    moRouteRespDTO.setProduceAmount(BigDecimal.ZERO);
                    BigDecimal amount = reportMap.get(moRouteRespDTO.getId());
                    if (ObjectUtil.isNotEmpty(amount)) {
                        moRouteRespDTO.setProduceAmount(amount);
                    }
                });
            }
            resp.setRoutes(routes);
        }
        return success(resp);
    }

    @GetMapping("/list")
    @Operation(summary = "获得生产排产列表")
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
    @PreAuthorize("@ss.hasPermission('mes:mo:query')")
    public CommonResult<List<MoRespVO>> getMoList(@RequestParam("ids") Collection<Long> ids) {
        List<MoDO> list = moService.getMoList(ids);
        return success(MoConvert.INSTANCE.convertList(list));
    }

    @GetMapping("/page")
    @Operation(summary = "获得生产排产分页")
    @PreAuthorize("@ss.hasPermission('mes:mo:query')")
    public CommonResult<PageResult<MoRespVO>> getMoPage(@Valid MoPageReqVO pageVO) {
        PageResult<MoDO> pageResult = moService.getMoPage(pageVO);
        PageResult<MoRespVO> resp = MoConvert.INSTANCE.convertPage(pageResult);
        resp.getList().forEach(moRespVO -> {
            //封装工厂信息
            FactoryRespDTO factory = factoryApi.getFactory(moRespVO.getFactoryId());
            if (ObjectUtil.isNotEmpty(factory)) {
                moRespVO.setFactoryName(factory.getName());
            }
            // 封装生产车间
            WorkshopRespDTO workshop = workshopApi.getWorkshop(moRespVO.getWorkshopId());
            if (ObjectUtil.isNotEmpty(workshop)) {
                moRespVO.setWorkshopName(workshop.getName());
            }
            // 封装生产计划
            PlanDO plan = planService.getPlan(moRespVO.getPlanId());
            if (ObjectUtil.isNotEmpty(plan)) {
                moRespVO.setPlanCode(plan.getCode());
            }
            // 封装部门
            DeptRespDTO dept = deptApi.getDept(moRespVO.getDeptId());
            if (ObjectUtil.isNotEmpty(dept)) {
                moRespVO.setDeptName(dept.getName());
            }
            //封装产品信息
            ItemRespDTO item = itemApi.getItem(moRespVO.getItemId());
            if (ObjectUtil.isNotEmpty(item)) {
                moRespVO.setItemName(item.getName());
                moRespVO.setItemCode(item.getCode());
                moRespVO.setSpec(item.getSpec());
                moRespVO.setDrawCode(item.getDrawCode());
            }
        });
        return success(resp);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出生产排产 Excel")
    @PreAuthorize("@ss.hasPermission('mes:mo:export')")
    @OperateLog(type = EXPORT)
    public void exportMoExcel(@Valid MoExportReqVO exportReqVO,
              HttpServletResponse response) throws IOException {
        List<MoDO> list = moService.getMoList(exportReqVO);
        // 导出 Excel
        List<MoExcelVO> datas = MoConvert.INSTANCE.convertList02(list);
        ExcelUtils.write(response, "生产排产.xls", "数据", MoExcelVO.class, datas);
    }


    @GetMapping("/forms")
    @Operation(summary = "获取生产进度报表")
    @PreAuthorize("@ss.hasPermission('mes:mo:forms')")
    public CommonResult<List<MoFormsRespVO>> getMoForms(@Valid MoFormsReqVO reqVO) {
        List<MoFormsRespVO> list = moService.getMoForms(reqVO);
        if (CollectionUtil.isNotEmpty(list)) {
            //提取工厂数据
            Set<Long> factoryIds = CollectionUtils.convertSet(list, MoFormsRespVO::getFactoryId);
            List<FactoryRespDTO> factoryRespDTOS = factoryApi.getFactoryList(factoryIds);
            Map<Long, FactoryRespDTO> factoryMap = CollectionUtils.convertMap(factoryRespDTOS, FactoryRespDTO::getId);
            //提取车间数据
            Set<Long> workshopIds = CollectionUtils.convertSet(list, MoFormsRespVO::getWorkshopId);
            List<WorkshopRespDTO> workshopRespDTOS = workshopApi.getWorkshopList(workshopIds);
            Map<Long, WorkshopRespDTO> workshopMap = CollectionUtils.convertMap(workshopRespDTOS, WorkshopRespDTO::getId);
            //提取产品数据
            Set<Long> itemIds = CollectionUtils.convertSet(list, MoFormsRespVO::getItemId);
            List<ItemRespDTO> itemRespDTOS = itemApi.getItemList(itemIds);
            Map<Long, ItemRespDTO> itemMap = CollectionUtils.convertMap(itemRespDTOS, ItemRespDTO::getId);
            //提取工艺信息
            Set<Long> processIds = CollectionUtils.convertSet(list, MoFormsRespVO::getProcessId);
            List<ProcessDO> processList = processService.getProcessList(processIds);
            Map<Long, ProcessDO> processMap = CollectionUtils.convertMap(processList, ProcessDO::getId);
            list.forEach(tmp -> {
                FactoryRespDTO factory = factoryMap.get(tmp.getFactoryId());
                if (ObjectUtil.isNotEmpty(factory)) {
                    tmp.setFactoryName(factory.getName());
                }
                WorkshopRespDTO workshop = workshopMap.get(tmp.getWorkshopId());
                if (ObjectUtil.isNotEmpty(workshop)) {
                    tmp.setWorkshopName(workshop.getName());
                }
                ItemRespDTO item = itemMap.get(tmp.getItemId());
                if (ObjectUtil.isNotEmpty(item)) {
                    tmp.setItemCode(item.getCode());
                    tmp.setItemName(item.getName());
                    tmp.setItemSpec(item.getSpec());
                    tmp.setDrawCode(item.getDrawCode());
                }
                ProcessDO process = processMap.get(tmp.getProcessId());
                if (ObjectUtil.isNotEmpty(process)) {
                    tmp.setProcessName(process.getName());
                }
            });
        }
        return success(list);
    }

}
